<template>
  <div className="panel">
    <h3>黑灰产网络资产子图</h3>
    <div id="cy" ref="cyContainer" style="height: 500px;"></div>
  </div>
</template>

<script setup>
import {onMounted, ref, defineExpose} from 'vue'
import cytoscape from 'cytoscape'

const cyContainer = ref(null)
let cy = null

// 模拟从后端获取图谱数据
const fetchGraphData = async () => {
  const res = await fetch('/graph')
  return await res.json()
}

onMounted(async () => {
  const data = await fetchGraphData()

  const elements = []

  // 添加节点
  data.nodes.forEach(n => {
    elements.push({
    {
      id: n.id, label: n.label,
        type: n.type
    }
  });
  });
  // 添加边
  data.edges.forEach(e => {
    elements.push({
    {
      source: e.source,
          target
    :
      e.target,
          label
    :
      e.label
    }
  })
  })

  cy = cytoscape({
    container: cyContainer.value,
    elements,
    style: [
      {
        selector: 'node',
        style: {
          'background-color': function (ele) {
            const type = ele.data('type')
            const colors = {Domain: '#ff6b6b', IP: '#4ecdc4', Cert: '#45b7d1', Whois: '#96ceb4'}
            return colors[type] || '#66a3ff'
          },
          'label': 'data(label)',
          'text-valign': 'center',
          'color': '#000',
          'font-size': '10px',
          'width': 30,
          'height': 30
        }
      },
      {
        selector: 'edge',
        style: {
          'width': 1,
          'line-color': '#ccc',
          'target-arrow-color': '#ccc',
          'target-arrow-shape': 'triangle',
          'curve-style': 'bezier',
          'label': 'data(label)' // 可选：显示边标签
        }
      }
    ],
    layout: {name: 'cose', animate: true, fit: true}
  })

  // 点击节点高亮邻居
  cy.on('tap', 'node', function (evt) {
    const node = evt.target
    cy.elements().removeClass('highlighted')
    node.addClass('highlighted')
    node.neighborhood().addClass('highlighted')
  })
})

const searchNode = (keyword) => {
  if (!cy) return
  const found = cy.nodes().filter(`[label *= "${keyword}"]`)
  if (found.length > 0) {
    cy.fit(found, 50)
    found.flashClass('flash', 1000)
  } else {
    alert('未找到匹配节点')
  }
}

const changeLayout = (layoutName) => {
  if (cy) {
    cy.layout({name: layoutName}).run()
  }
}

const resetView = () => {
  if (cy) {
    cy.fit()
  }
}

defineExpose({
  searchNode,
  changeLayout,
  resetView
})
</script>

<style scoped>
.panel {
  background: white;
  margin-bottom: 15px;
  padding: 15px;
  border-radius: 8px;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
</style>